/*
*    TG_Code : Dzlua
*    Email   : 505544956@qq.com
*    Time    : 2017/07/28
*/

#pragma once

#include <memory>
#include <WinSock2.h>

/*
*	package length, action, local socket, remote socket, data length, data
*	request->header->disconnected->disconnected from client->return data
*/
namespace tg {

namespace Package {

enum class eAction : uint8_t {
    unknown, request, header, dis_conn,
    dis_conn_client, had_data
};

} // end namespace package

class PackageRead {
public:
    PackageRead(const char *buffer, size_t len);
    ~PackageRead();
public:
    bool IsOK();
    uint16_t GetLength();
    Package::eAction GetAction();
    SOCKET GetLocalSocket();
    SOCKET GetRemoteSocket();
    uint16_t GetDataLength();
    const char* GetDataBuffer();
    // only for eAction::request
    sockaddr_in GetRemoteAddr();
    void SetRemoteAddr(sockaddr_in &addr);
    // only for eAction::request
    uint16_t GetRequestDataLength();
    // only for eAction::request
    const char* GetRequestDataBuffer();
protected:
    size_t len_;
    char* buffer_;
};

class PackageWrite {
public:
    PackageWrite();
    ~PackageWrite();
public:
    void Commit();
    const char* GetDataBuffer();
    uint16_t GetDataLength();
    void Reset();
#ifdef DEBUG
    void Dump();
#endif
public:
    void SetAction(Package::eAction act);
    void SetLocalSocket(SOCKET sock);
    void SetRemoteSocket(SOCKET sock);
    void SetDataLength(uint16_t len);
    void SetData(const char* data);
protected:
    void CalculateBufferSize();
protected:
    char *buffer_;
    uint16_t buf_len_;
    //
    Package::eAction action_;
    SOCKET sock_local_;
    SOCKET sock_remote_;
    uint16_t data_len_;
    const char* data_buf_;
};

} // end namespace tg